import pandas as pd
import numpy as np
from pandas import Series
from sklearn.cluster import KMeans
from datetime import datetime
from sklearn.cluster import KMeans
from datetime import datetime
from .datetime_tools import monthday_to_dayofyear

# 设置输出对齐方式
pd.set_option('display.unicode.ambiguous_as_wide', True)  # 把模糊字符视为宽字符
pd.set_option('display.unicode.east_asian_width', True)  # 把东亚字符视为宽字符
pd.set_option('display.width', 180)  # 设置打印宽度，根据需要调整


def calculate_date_scores(se_date: Series, n=30) -> Series:
    # null_count = se_date.isna().sum()
    # print("空值数量：", null_count)  # 输出：4（None、np.nan、pd.NA、"" 均被识别为空值）
    se_date = se_date.dropna()

    # region 2: 处理原始Series：生成"年内第N天"的Series
    dayofyear_series = se_date.apply(monthday_to_dayofyear)
    # endregion


    # region 3. 逆序处理：早日期（小dayofyear）对应大数值，与分数正相关
    max_day = 366  # 2024是闰年，确保覆盖所有日期；平年用365
    reversed_series = max_day - dayofyear_series
    # endregion

    # region 4. 用4分位数划分4个区间（25%、50%、75%分位数）
    quantiles = reversed_series.quantile([0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875]).values  # 得到3个分位数阈值
    q1, q2, q3, q4, q5, q6, q7 = quantiles[0], quantiles[1], quantiles[2], quantiles[3], \
        quantiles[4], quantiles[5], quantiles[6]

    # endregion

    # region 5. 定义分数映射函数：按区间分配55-95的分数
    def map_to_score(value):
        if value >= q7:  # 最早的日期（逆序值最大）→ 最高分数区间
            score = np.random.uniform(90, 95)  # 随机数避免分数完全重复
        elif value >= q6:
            score = np.random.uniform(85, 90)
        elif value >= q5:
            score = np.random.uniform(80, 85)
        elif value >= q4:
            score = np.random.uniform(75, 80)
        elif value >= q3:
            score = np.random.uniform(70, 75)
        elif value >= q2:
            score = np.random.uniform(65, 70)
        elif value >= q1:
            score = np.random.uniform(60, 65)
        else:  # 最晚的日期（逆序值最小）→ 最低分数区间
            score = np.random.uniform(55, 60)

        return score

    # endregion

    # region 6. 定义学校函数：将区间 [min,max] 中的值缩小到 [n/2, n] 之间。
    def scale_series(s: Series, original_min: int, original_max: int, n: int):
        """
         将60-100区间的Series缩放至[n/2, n]区间

         参数：
             s: 数值类型的Series（值在60-100之间）
             n: 目标区间的最大值
         返回：
             缩放后的Series
         """
        # original_min = 60
        # original_max = 100
        target_min = n / 2
        target_max = n

        # 应用线性缩放公式
        scaled_s = (s - original_min) / (original_max - original_min) * (target_max - target_min) + target_min
        return scaled_s

    # endregion

    # region 7. 生成最终分数Series（可按需保留小数或取整）
    score_series = reversed_series.apply(map_to_score).round(1)  # 保留1位小数
    # endregion

    #
    se_最终分数 = scale_series(score_series, 55, 95, n).astype(int)
    return se_最终分数


if __name__ == "__main__":
    s = pd.Series(['0105', '0312', '0520', '0730', '0915', '1125', '1230', '0218', '0422', '0610'])
    se_最终分数 = calculate_date_scores(s, 50)
    # 查看结果：日期、天数、逆序值、分数的对应关系
    # se_最终分数 = scale_series(np.floor(score_series).astype(int), 60, 100, 30)
    result_df = pd.DataFrame({
        '原始日期': s,
        '最终分数': se_最终分数  # np.floor(score_series).astype(int)
    })
    print(result_df)
